package com.dalonedrow.module.hq;

import java.nio.Buffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.FPSLogger;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.GL11;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.BufferUtils;
import com.dalonedrow.engine.sprite.base.SpriteBase;
import com.dalonedrow.engine.sprite.base.SpriteImageObjectFactory;
import com.dalonedrow.engine.sprite.impl.SoftwareCursor;
import com.dalonedrow.engine.systems.JOGLErrorHandler;
import com.dalonedrow.engine.systems.Render;
import com.dalonedrow.engine.systems.Time;
import com.dalonedrow.engine.systems.base.Animation;
import com.dalonedrow.engine.systems.base.InputEvent;
import com.dalonedrow.engine.systems.base.Interface;
import com.dalonedrow.engine.systems.base.Particle;
import com.dalonedrow.engine.systems.base.ProjectConstants;
import com.dalonedrow.engine.systems.base.Script;
import com.dalonedrow.globalvariables.constants.hq.GlobalConstants;
import com.dalonedrow.module.hq.systems.HQController;
import com.dalonedrow.utils.TextureLoader;

/**
 * The application entry point.
 * @author Donald
 *
 */
public final class DawnQuestGame implements ApplicationListener {
	/** the singleton instance of {@link DawnQuestGame}. */
	private static DawnQuestGame	instance;
	/**
	 * Gets the instance
	 * @return {@link DawnQuestGame}
	 */
	public static DawnQuestGame getInstance() {
		return DawnQuestGame.instance;
	}
	/** a libgdx helper class that logs the current FPS each second. */
	private FPSLogger	fpsLogger;
	/** the handle to the vertex buffer object. */
	private int			vboHandle;
	/** the handle to the index buffer object. */
	private int iboHandle;
    ShortBuffer indices;
    FloatBuffer vertices1;
    FloatBuffer vertices2;
    FloatBuffer vertices3;
	@Override
	public void create() {
		try {
			DawnQuestGame.instance = this;
			GL11 gl = Gdx.graphics.getGL11();
			Gdx.input.setInputProcessor(Interface.getInstance());
			// mine
			gl.glClearColor(0, 0, 0, 1);
			gl.glShadeModel(GL10.GL_SMOOTH);
			gl.glEnable(GL10.GL_BLEND);
			gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
			float w = Gdx.graphics.getWidth();
			float h = Gdx.graphics.getHeight();

			gl.glViewport(0, 0, (int) w, (int) h);
			gl.glMatrixMode(GL10.GL_PROJECTION);
			gl.glLoadIdentity();
			if (w <= h) {
				gl.glOrthof(
						0f, // left
						w, // right
						0f, // bottom
						h, // top
						-1.0f, // near
						1.0f); // far
			} else {
				gl.glOrthof(
						0f, // left
						w, // right
						0f, // bottom
						h, // top
						-1.0f, // near
						1.0f); // far
			}
			gl.glMatrixMode(GL10.GL_MODELVIEW);
			gl.glLoadIdentity();
			// load assets
			new HQController();
			IntBuffer handleBuf = BufferUtils.newIntBuffer(2);
			gl.glGenBuffers(2, handleBuf);
			vboHandle = handleBuf.get(0);
			iboHandle = handleBuf.get(1);

            indices = BufferUtils.newShortBuffer(12);
            indices.put(new short[] {
            		0, 1, 2, 2, 3, 0,
            		4, 5, 6, 6, 7, 4
            		});
            indices.flip();

            float c = Color.toFloatBits(1f, 1f, 1f, 1f);
            vertices1 = BufferUtils.newFloatBuffer(20);
            vertices1.put(new float[] {
           		16,  334, 0,       0.125f, c, // BL 1
           		16, 366, 0,       0.0625f,       c, // TL 1
           		48, 366, 0.0625f, 0.0625f,       c, // TR 2
           		48,  334, 0.0625f, 0.125f, c // BR 3
            });
            vertices1.flip();
            vertices3 = BufferUtils.newFloatBuffer(20);
            vertices3.put(new float[] {
           		0,  0, 0,       0.68359375f, c, // BL 1
           		0, 350, 0,       0,       c, // TL 1
           		258, 350, 0.50390625f, 0,       c, // TR 2
           		258,  0, 0.50390625f, 0.68359375f, c // BR 3
            });
            vertices3.flip();
            vertices2 = BufferUtils.newFloatBuffer(20);
            vertices2.put(new float[] {
            		 0,  0, 0,       0.0625f, c, // BL 1
            		 0, 32, 0,       0,       c, // TL 1
            		32, 32, 0.0625f, 0,       c, // TR 2
            		32,  0, 0.0625f, 0.0625f, c // BR 3
            		});
            vertices2.flip();
			fpsLogger = new FPSLogger();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	private void fillBuffers() {
		
	}
	@Override
	public void dispose() {}
	/** Disposes of all resources and exits the application. */
	public void end() {
		dispose();
		Gdx.app.exit();
	}
	/**
	 * Gets the handle to the index buffer object.
	 * @return <code>int</code>
	 */
	public int getIBO() {
		return iboHandle;
	}
	/**
	 * Gets the handle to the vertex buffer object.
	 * @return <code>int</code>
	 */
	public int getVBO() {
		return vboHandle;
	}
	/** Initializes cursors. Not used, due to the errors with libGDX. */
	private void initCursors() {

	}
	@Override
	public void pause() {}
	@Override
	public void render() {
		try {
			update();
			GL11 gl = Gdx.graphics.getGL11();
			gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
			Render.getInstance().render();
			//SoftwareCursor.getInstance().render();
			fpsLogger.log();
		} catch (Exception ex) {
			ex.printStackTrace();
			JOGLErrorHandler.getInstance().fatalError(ex);
		}
	}
	@Override
	public void resize(int width, int height) {}

	@Override
	public void resume() {}
	/**
	 * Updates the game cycle.
	 * @throws Exception if an error occurs
	 */
	private void update() throws Exception {
		// mark the start of the frame
		Time.getInstance().startFrame();
		// update events
		InputEvent.getInstance().processActions();
		// update scripts
		Script.getInstance().update();
		// update animations
		Animation.getInstance().update();
		// update particles
		Particle.getInstance().update();
		// update game controller
		ProjectConstants.getInstance().update();
		// check interface for events
		Interface.getInstance().gameUpdate();
		// reset the mouse position
		Interface.getInstance().setMouseLoc(
				Gdx.input.getX(), Gdx.input.getY());
		// render the screen
		Interface.getInstance().prepareForRendering();
	}
}
